package edu.gatech.cs2340.teamrocket.model.map;

import java.util.List;
import java.util.ArrayList;
import java.io.Serializable;
import edu.gatech.cs2340.teamrocket.model.storage.ShopInventory;

/**
 * This class will represent the map of Locations.
 *
 * @author Joe Tacheron
 */
public class Map implements Serializable {

    // City names
    private static final String CITY_NAME_1 = "Viridian City";
    private static final String CITY_NAME_2 = "Pewter City";
    private static final String CITY_NAME_3 = "Cerulean City";
    private static final String CITY_NAME_4 = "Vermilion City";
    private static final String CITY_NAME_5 = "Celadon City";
    private static final String CITY_NAME_6 = "Fuchsia City";
    private static final String CITY_NAME_7 = "Saffron City";

    // Town names
    private static final String TOWN_NAME_1 = "Lavender Town";
    private static final String TOWN_NAME_2 = "Mossgreen Village";
    private static final String TOWN_NAME_3 = "Silver Town";
    private static final String TOWN_NAME_4 = "Mulberry Town";

    // Forest names
    private static final String FOREST_NAME_1 = "Viridian Forest";
    private static final String FOREST_NAME_2 = "Leaf Forest";

    // Plains names
    private static final String PLAINS_NAME_1  = "Route 1";
    private static final String PLAINS_NAME_2  = "Route 2";
    private static final String PLAINS_NAME_3  = "Route 3";
    private static final String PLAINS_NAME_4  = "Route 4";
    private static final String PLAINS_NAME_5  = "Route 5";
    private static final String PLAINS_NAME_6  = "Route 6";
    private static final String PLAINS_NAME_7  = "Route 7";
    private static final String PLAINS_NAME_8  = "Route 8";
    private static final String PLAINS_NAME_9  = "Route 9";
    private static final String PLAINS_NAME_10 = "Route 10";
    private static final String PLAINS_NAME_11 = "Route 11";
    private static final String PLAINS_NAME_12 = "Route 12";
    private static final String PLAINS_NAME_13 = "Route 13";
    private static final String PLAINS_NAME_14 = "Route 14";
    private static final String PLAINS_NAME_15 = "Route 15";
    private static final String PLAINS_NAME_16 = "Safari Zone";
    private static final String PLAINS_NAME_17 = "Route 16";
    private static final String PLAINS_NAME_18 = "Cycling Road";
    private static final String PLAINS_NAME_19 = "Route 18";
    private static final String PLAINS_NAME_20 = "Route 19";
    private static final String PLAINS_NAME_21 = "Route 20";
    private static final String PLAINS_NAME_22 = "Route 21";
    private static final String PLAINS_NAME_23 = "Route 22";
    private static final String PLAINS_NAME_24 = "Route 23";
    private static final String PLAINS_NAME_25 = "Route 24";
    private static final String PLAINS_NAME_26 = "Route 25";

    // Mountain names
    private static final String MOUNTAIN_NAME_1 = "Mt. Moon";
    private static final String MOUNTAIN_NAME_2 = "Fennel Valley";
    private static final String MOUNTAIN_NAME_3 = "Mt. Hideaway";
    private static final String MOUNTAIN_NAME_4 = "Maiden's Peak";

    // Lakeside names
    private static final String LAKESIDE_NAME_1 = "Cinnabar Island";
    private static final String LAKESIDE_NAME_2 = "Seafoam Islands";
    private static final String LAKESIDE_NAME_3 = "Metallica Island";
    private static final String LAKESIDE_NAME_4 = "Camomile Island";

    // Cave names
    private static final String CAVE_NAME_1 = "Cerulean Cave";
    private static final String CAVE_NAME_2 = "Diglett's Cave";

    // distance between Locations
    private static final int DISTANCE_BEWTWEEN = 15;

    // list of Locations
    private static final List<Location> locations;

    /**
     * Generate a the same map every game.
     */
    static {
        locations = new ArrayList<Location>();
        int distance = 0;

        locations.add(LocationFactory.getStart());
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_1, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_2, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getForest(FOREST_NAME_1, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getCity(CITY_NAME_1, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_3, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_4, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_5, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getTown(TOWN_NAME_1, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getForest(FOREST_NAME_2, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_6, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_7, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getCave(CAVE_NAME_1, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getTown(TOWN_NAME_2, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_8, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_9, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_10, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_11, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getTown(TOWN_NAME_3, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_12, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getMountain(MOUNTAIN_NAME_1, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_13, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getMountain(MOUNTAIN_NAME_2, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getLakeside(LAKESIDE_NAME_1, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getCity(CITY_NAME_2, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getLakeside(LAKESIDE_NAME_2, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getLakeside(LAKESIDE_NAME_3, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getLakeside(LAKESIDE_NAME_4, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getTown(TOWN_NAME_4, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_14, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_15, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_16, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_17, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getCity(CITY_NAME_3, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_18, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_19, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getMountain(MOUNTAIN_NAME_3, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getCity(CITY_NAME_4, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_20, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_21, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getCity(CITY_NAME_5, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_22, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_23, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getCave(CAVE_NAME_2, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getCity(CITY_NAME_6, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_24, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_25, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getCity(CITY_NAME_7, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getMountain(MOUNTAIN_NAME_4, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getPlains(PLAINS_NAME_26, distance));
        distance += DISTANCE_BEWTWEEN;
        locations.add(LocationFactory.getEnd(distance));
    }

    private int distanceTraveled;
    private int pos;

    /**
     * Move forward the given distance and change the current Location if
     * necessary.
     *
     * @param dist the distance traveled
     * @return the new Location if one was reached
     */
    public Location moveForward(int dist){
        Location newLocation = null;
        distanceTraveled += dist;
        while(distanceTraveled > getCurrentLocation().getEndDist()){
            pos++;
            newLocation = locations.get(pos);
        }
        return newLocation;
    }

    /**
     *
     * @return true if at the end of the map, false otherwise
     */
    public boolean atEnd(){
        return locations.size() == 1;
    }

    /**
     * @return The distance traveled from the starting pos.
     */
    public int getDistTravel() {
        return distanceTraveled;
    }

    /**
     * @param distTravel The distance to set the player to having traveled.
     */
    public void setDistTravel(int distTravel) {
        this.distanceTraveled = distTravel;
    }

    /**
     * @return The current Location
     */
    public Location getCurrentLocation() {
        return locations.get(pos);
    }

    /**
     *
     * @return true if the current location has a shop, false otherwise
     */
    public boolean hasLocalShop(){
        return locations.get(pos).hasShop();
    }

    /**
     *
     * @return the ShopInventory of the current Location
     */
    public ShopInventory getLocalShop(){
        return locations.get(pos).getShop();
    }

    /**
     *
     * @return all Locations
     */
    public List<Location> getLocations(){
    	return locations;
    }

    /**
     *
     * @return an HTML-formatted String representation of this Map
     */
    public String toHTML(){
        StringBuilder retval = new StringBuilder();

        retval.append("<html>");
        retval.append("<font size='3'>");
        retval.append("<p>");
        retval.append("Location: ");
        retval.append(getCurrentLocation().getName());
        retval.append("</p>");
        retval.append("<p>");
        retval.append("Type: ");
        retval.append(getCurrentLocation().getType());
        retval.append("</p>");
        retval.append("</font>");
        retval.append("</html>");

        return retval.toString();
    }
}